
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Helper;
using IRepository;
using Models;
using System.Linq;
using Models.Entity;
using MySql.Data.MySqlClient;
using Dapper;
using System.Data;
using System.Linq.Expressions;

namespace Repository
{
    /// <summary>
    /// 报表
    /// </summary>
    public class ReportRepository : IReportRepository
    {
        DapperHelper<CWeekCourseEntity> dbHelper = new DapperHelper<CWeekCourseEntity>();
        DapperHelper<CWeekCourseEntityView> dbHelper_v = new DapperHelper<CWeekCourseEntityView>();
        DapperHelper<CClassesWeekCourseEntityView> dbHelper_WeekCourseV = new DapperHelper<CClassesWeekCourseEntityView>();
        DapperHelper<CWeekCourseChangeEntity> dbHelper_change = new DapperHelper<CWeekCourseChangeEntity>();
        DapperHelper<CWeekCourseCancelEntity> dbHelper_cancel = new DapperHelper<CWeekCourseCancelEntity>();
        DapperHelper<CWeekCourseCancelEntityView> dbHelper_cancelView = new DapperHelper<CWeekCourseCancelEntityView>();


        /// <summary>
        /// 获取老师的课时统计
        /// </summary>
        /// <param name="inEnt"></param>
        /// <returns></returns>
        public async Task<ResultObj<ResultTeacherReport>> TeacherCourseReport(DtoTeachReport inEnt)
        {
            var reObj = new ResultObj<ResultTeacherReport>();
            var startTime = new DateTime();
            var endTime = new DateTime();

            Int64 startTimeInt64;
            Int64 endTimeInt64;
            if (!DateTime.TryParse(inEnt.dtStart, out startTime))
            {
                reObj.success = false;
                reObj.msg = "开始时间格式有误";
                return reObj;
            }
            if (!DateTime.TryParse(inEnt.dtEnd, out endTime))
            {
                reObj.success = false;
                reObj.msg = "结束时间格式有误";
                return reObj;
            }
            startTimeInt64 = DateTimeHelper.getDateLong(startTime);
            endTimeInt64 = DateTimeHelper.getDateLong(endTime);
            var totalDays = (endTime - startTime).TotalDays;
            if (totalDays <= 0)
            {
                reObj.success = false;
                reObj.msg = "时间顺序有误";
                return reObj;
            }

            var teacherCourseList = await dbHelper_v.FindAll(x => x.teacher_id == inEnt.teacherId);
            Dictionary<int, List<CWeekCourseEntityView>> weekDic = new Dictionary<int, List<CWeekCourseEntityView>>();
            string idArrStr = string.Join(",", teacherCourseList.Select(x => x.week_course_id));
            var changeList = await dbHelper_change.FindAll($"week_course_id1 in ({idArrStr}) or week_course_id2 in ({idArrStr})");

            var cancelList = await dbHelper_cancel.FindAll(x => x.cancel_date >= startTimeInt64 && x.cancel_date <= endTimeInt64);

            foreach (var item in teacherCourseList.GroupBy(x => x.order_num % 10))
            {
                weekDic.Add(item.Key, item.ToList());
            }

            var weekNum = (Convert.ToInt32(totalDays) + 1) / 7;
            if (weekNum % 7 != 0) weekNum = weekNum + 1;
            //星期0，表示周日
            for (int i = 0; i < 7; i++)
            {
                if (!weekDic.ContainsKey((int)startTime.AddDays(i).DayOfWeek))
                {
                    continue;
                }

                var dayCourseList = weekDic[(int)startTime.AddDays(i).DayOfWeek];
                var orderNumList = dayCourseList.Select(x => x.order_num / 10).ToList();
                for (int w = 0; w < weekNum; w++)
                {
                    var tmpData = startTime.AddDays(w * 7 + i);
                    if (tmpData <= endTime)
                    {
                        foreach (var weekCourse in dayCourseList)
                        {
                            // 有取消的，则过滤掉
                            if (
                                cancelList.Count(x => x.week_course_id == weekCourse.week_course_id && (x.cancel_date / 1000000) == Convert.ToInt64(tmpData.ToString("yyyyMMdd"))) > 0)
                            {
                                continue;
                            }

                            var className = string.Join(",", (await dbHelper_WeekCourseV.FindAll(x => x.week_course_id == weekCourse.week_course_id)).Select(x => x.classes_name));
                            var tmpChangeList = changeList.SingleOrDefault(x => x.week_course_id1 == weekCourse.week_course_id || x.week_course_id2 == weekCourse.week_course_id);
                            var changeId = "";
                            int orderNum = weekCourse.order_num;
                            if (tmpChangeList != null)
                            {
                                changeId = tmpChangeList.id.ToString();
                                if (tmpChangeList.week_course_id1 == weekCourse.week_course_id)
                                {
                                    orderNum = (await dbHelper.Single(x => x.week_course_id == tmpChangeList.week_course_id2)).order_num;
                                }
                                else
                                {
                                    orderNum = (await dbHelper.Single(x => x.week_course_id == tmpChangeList.week_course_id1)).order_num;
                                }
                            }

                            reObj.dataList.Add(new ResultTeacherReport
                            {
                                dateStr = $"{tmpData.ToString("yyyy-MM-dd")}(周{(int)tmpData.DayOfWeek})",
                                weekCourseId = weekCourse.week_course_id,
                                orderNum = orderNum / 10,
                                orderNumStr = $"第{orderNum / 10}节：{className}",
                                ChangeId = changeId
                            });
                        }
                    }

                }
            }
            reObj.dataList = reObj.dataList.OrderBy(x => x.dateStr).ToList();
            reObj.total = reObj.dataList.Count();
            reObj.success = true;
            return reObj;
        }

        /// <summary>
        /// 获取老师的课时统计汇总
        /// </summary>
        /// <param name="inEnt"></param>
        /// <returns></returns>
        public async Task<ResultObj<TeachWeekReport>> TeacherAllCourseReport(DtoTeachReport inEnt)
        {
            ResultObj<TeachWeekReport> reObj = new ResultObj<TeachWeekReport>();
            try
            {


                var startTime = new DateTime();
                var endTime = new DateTime();

                Int64 startTimeInt64;
                Int64 endTimeInt64;
                if (!DateTime.TryParse(inEnt.dtStart, out startTime))
                {
                    reObj.success = false;
                    reObj.msg = "开始时间格式有误";
                    return reObj;
                }
                if (!DateTime.TryParse(inEnt.dtEnd, out endTime))
                {
                    reObj.success = false;
                    reObj.msg = "结束时间格式有误";
                    return reObj;
                }
                startTime = Convert.ToDateTime(startTime.ToString("yyyy-MM-dd"));
                endTime = Convert.ToDateTime(endTime.ToString("yyyy-MM-dd"));
                endTime = endTime.AddDays(1);

                reObj.dataList = new List<TeachWeekReport>();
                string sql = @"
	SELECT		
		c.teacher_id,
		c.`name`,
		count(1) num ,
		count(case when a.order_num % 10 =1 then '1' end) w1,
		count(case when a.order_num % 10 =2 then '1' end) w2,
		count(case when a.order_num % 10 =3 then '1' end) w3,
		count(case when a.order_num % 10 =4 then '1' end) w4,
		count(case when a.order_num % 10 =5 then '1' end) w5,
		count(case when a.order_num % 10 =6 then '1' end) w6
	FROM
		c_week_course a
		LEFT JOIN c_teacher_course b ON a.teacher_course_id = b.teacher_course_id
		LEFT JOIN c_teacher c ON c.teacher_id = b.teacher_id
		LEFT JOIN c_course d ON d.course_id = b.course_id
	GROUP BY
		c.teacher_id,
		c.`name`
            ";


                startTimeInt64 = DateTimeHelper.getDateLong(startTime);
                endTimeInt64 = DateTimeHelper.getDateLong(endTime);

                var cancelList = await dbHelper_cancelView.FindAll(x => x.cancel_date >= startTimeInt64 && x.cancel_date <= endTimeInt64);
                IEnumerable<TeachWeekReport> data = await dbHelper.QueryAsync<TeachWeekReport>(sql);
                int allDay = Convert.ToInt32((endTime - startTime).TotalDays);
                int weekNum = allDay / 7;

                foreach (var item in data)
                {
                    TeachWeekReport addEnt = new TeachWeekReport();
                    addEnt.teacherId = item.teacherId;
                    addEnt.name = item.name;
                    addEnt.cancelNum = cancelList.Count(x => x.teacher_id == addEnt.teacherId);
                    addEnt.w1 = weekNum * item.w1;
                    addEnt.w2 = weekNum * item.w2;
                    addEnt.w3 = weekNum * item.w3;
                    addEnt.w4 = weekNum * item.w4;
                    addEnt.w5 = weekNum * item.w5;
                    addEnt.w6 = weekNum * item.w6;

                    for (int i = 0; i < allDay % 7; i++)
                    {
                        var tmpData = startTime.AddDays(i);
                        switch ((int)tmpData.DayOfWeek)
                        {
                            case 1:
                                addEnt.w1 += item.w1;
                                break;
                            case 2:
                                addEnt.w2 += item.w2;
                                break;
                            case 3:
                                addEnt.w3 += item.w3;
                                break;
                            case 4:
                                addEnt.w4 += item.w4;
                                break;
                            case 5:
                                addEnt.w5 += item.w5;
                                break;
                            case 6:
                                addEnt.w6 += item.w6;
                                break;
                        }
                    }

                    addEnt.num = addEnt.w1 + addEnt.w2 + addEnt.w3 + addEnt.w4 + addEnt.w5 + addEnt.w6 - addEnt.cancelNum;

                    reObj.dataList.Add(addEnt);
                }
                reObj.success = true;

            }
            catch (System.Exception e)
            {
                reObj.success = false;
                reObj.msg = e.Message;
            }
            return reObj;
        }
    }
}
